
package jleda.list;

import java.util.*;

public class ArrayListDouble implements Iterable<Double> {
	private static final int DEFAULT_SIZE = 8;
	private static final int RESIZE_FACTOR = 2;
	private double[] arr;
	private int size;
	
	public ArrayListDouble() {
		arr = new double[DEFAULT_SIZE];
		size = 0;
	}
	
	public ArrayListDouble( int initsize ) {
		arr = new double[initsize];
		this.size = 0;
	}
	
	public void add( int index, double data ) {
		if( size == arr.length ) {
			double[] t = new double[RESIZE_FACTOR * size];
			System.arraycopy( arr, 0, t, 0, index );
			System.arraycopy( arr, index, t, index + 1, size - index );
			arr = t;
		} else
			System.arraycopy( arr, index, arr, index + 1, size - index );
		
		arr[index] = data;
		size++;
	}
	
	public void addFirst( double data ) {
		if( size == arr.length ) {
			double[] t = new double[RESIZE_FACTOR * size];
			System.arraycopy( arr, 0, t, 1, size );
			arr = t;
		}
		
		arr[0] = data;
		size++;
	}
	
	public void addLast( double data ) {
		if( size == arr.length ) {
			double[] t = new double[RESIZE_FACTOR * size];
			System.arraycopy( arr, 0, t, 0, size );
			arr = t;
		}
		
		arr[size] = data;
		size++;
	}
	
	public double getFirst() {
		return arr[0];
	}
	
	public double getLast() {
		return arr[size - 1];
	}
	
	public double get( int index ) {
		return arr[index];
	}
	
	public void set( int index, double data ) {
		arr[index] = data;
	}
	
	// untested
	public double removeFirst() {
		double v = arr[0];
		size--;
		System.arraycopy( arr, 1, arr, 0, size );
		return v;
	}
	
	// untested
	public double removeLast() {
		size--;
		return arr[size];
		
	}
	
	public double remove( int index ) {
		double t = arr[index];
		size--;
		System.arraycopy( arr, index + 1, arr, index, size - index );
		return t;
	}
	
	public String toString() {
		if( size == 0 )
			return "[]";
		
		StringBuilder sb = new StringBuilder( "[" + arr[0] );
		
		for( int i = 1; i < size; i++ )
			sb.append( ", " ).append( arr[i] );
		
		return sb.append( ']' ).toString();
	}
	
	public boolean removeElement( double data ) {
		for( int i = 0; i < size; i++ )
			if( arr[i] == data ) {
				size--;
				System.arraycopy( arr, i + 1, arr, i, size - i );
				return true;
			}
		
		return false;
	}
	
	// untested
	public boolean removeAll( Collection<Double> c ) {
		boolean flag = false;
		
		for( Double data : c )
			if( removeElement( data ) ) {
				flag = true;
			}
		
		return flag;
	}
	
	public void clear() {
		size = 0;
	}
	
	public boolean contains( double data ) {
		for( int i = 0; i < size; i++ )
			if( arr[i] == data )
				return true;
		
		return false;
	}
	
	public boolean containsAll( Collection<Double> c ) {
		for( Double data : c ) {
			boolean flag = false;
			
			for( int i = 0; i < size; i++ )
				if( arr[i] == data ) {
					flag = true;
					break;
				}
			
			if( !flag )
				return false;
		}
		
		return true;
	}
	
	public int size() {
		return size;
	}
	
	public boolean isEmpty() {
		return size == 0;
	}
	
	public void trimToSize() {
		if( size != arr.length ) {
			double[] t = new double[size];
			System.arraycopy( arr, 0, t, 0, size );
			arr = t;
		}
	}
	
	public Iterator<Double> iterator() {
		return new ALIterator();
	}
	
	public ListIterator<Double> listIterator() {
		return new ALIterator();
	}
	
	public ListIterator<Double> listIterator( int index ) {
		return new ALIterator( index );
	}
	
	// untested
	private class ALIterator implements ListIterator<Double> {
		int prevIndex = 0, nextIndex = 0;
		
		ALIterator() {
			
		}
		
		ALIterator( int index ) {
			this.nextIndex = index;
		}
		
		public Double next() {
			return arr[prevIndex = nextIndex++];
		}
		
		public Double previous() {
			return arr[prevIndex = --nextIndex];
		}
		
		public void add( Double data ) {
			if( size == arr.length ) {
				double[] t = new double[RESIZE_FACTOR * size];
				System.arraycopy( arr, 0, t, 0, nextIndex );
				System.arraycopy( arr, nextIndex, t, nextIndex + 1, size - nextIndex );
				arr = t;
			} else
				System.arraycopy( arr, nextIndex, arr, nextIndex + 1, size - nextIndex );
			
			arr[nextIndex++] = data;
			size++;
		}
		
		public void set( Double data ) {
			arr[prevIndex] = data;
		}
		
		public void remove() {
			size--;
			System.arraycopy( arr, prevIndex + 1, arr, prevIndex, size - prevIndex );
		}
		
		public boolean hasNext() {
			return nextIndex != size;
		}
		
		public boolean hasPrevious() {
			return nextIndex != 0;
		}
		
		public int nextIndex() {
			return nextIndex;
		}
		
		public int previousIndex() {
			return nextIndex - 1;
		}
	}
}
